#include "graphic_task.h"
#include "referee.h"
#include "ui_interface.h"
#include "referee.h"

#define GET_ID(s,p,v) (((s)<<16)|((p)<<8)|((v)))//使用3个byte值构建图形ID
static graphic_data_struct_t graphic_buffer[GRAPHIC_BUFFER_SIZE];
static uint16_t buffer_next_read = 0;
static uint16_t buffer_next_write = 0;
static uint16_t buffer_size = 0;

static graphic_data_struct_t data_trashed;//充当垃圾桶，当缓冲区满后，所有要写入的数据都会被写入到这里，不需要管它
static toREF_t toREF_data;


/// @brief 从数据流中读取一个图形数据项
/// @return 读取的图形数据项。如果没有可以读取的（缓冲区空），返回0
graphic_data_struct_t* graphic_buffer_read()
{
    if (buffer_size == 0) {
        return 0;
    }
    graphic_data_struct_t* re = &graphic_buffer[buffer_next_read];
    buffer_next_read = (buffer_next_read + 1) % GRAPHIC_BUFFER_SIZE;
    buffer_size -= 1;
    return re;
}
/// @brief 向数据流中写入图形数据项
/// @return 写入的数据。如果没有可以写入的（缓冲区满），返回垃圾桶
graphic_data_struct_t* graphic_buffer_write()
{
    if (buffer_size == GRAPHIC_BUFFER_SIZE) {
        return &data_trashed;
    }
    graphic_data_struct_t* re = &graphic_buffer[buffer_next_write];
    buffer_next_write = (buffer_next_write + 1) % GRAPHIC_BUFFER_SIZE;
    buffer_size += 1;
    return re;
}

/// @brief 初始化并绘制一些背景控件
void graphic_init()
{
    graphic_set_super_cup(200);
    graphic_set_chassis_angle(170);
    
    graphic_draw_circle(graphic_data_set_inf(graphic_buffer_write(),//超级电容外框
        GET_ID(0, 0, 0),//图形ID
        Graphic_OP_Add,//图形操作
        0,//图层
        Graphic_Color_Yellow//颜色
    ),
        10,//线宽
        (graphic_point) {
        GRAPHIC_SCREEN_WIDTH-1920+1681, 558//圆心位置
    },
        80//半径
    );
    graphic_draw_rect(graphic_data_set_inf(graphic_buffer_write(),//底盘外框
        GET_ID(0, 1, 0),//图形ID
        Graphic_OP_Add,//图形操作
        0,//图层
        Graphic_Color_Yellow//颜色
    ),
        10,//线宽
        (graphic_point) {
        GRAPHIC_SCREEN_WIDTH / 2 - GRAPHIC_CHASSIS_WIDTH / 2, -50//左下角位置
    },
        (graphic_point) {
        GRAPHIC_SCREEN_WIDTH / 2 + GRAPHIC_CHASSIS_WIDTH / 2, GRAPHIC_CHASSIS_HEIGHT//右上角位置
    }
    );
}

static uint8_t super_cup_val_tmp;
static int16_t chassis_theta_tmp;

void graphic_set_super_cup(uint8_t val) {
    super_cup_val_tmp = val;
}
void graphic_set_chassis_angle(int16_t theta) {
    chassis_theta_tmp = theta;
}

void graphic_draw_super_cup(uint8_t val) {
    static bool_t drawed = 0;
    graphic_draw_arc(graphic_data_set_inf(graphic_buffer_write(),
        GET_ID(1, 0, 0),
        drawed ? Graphic_OP_Change : (drawed = 1, Graphic_OP_Add),
        1,
        Graphic_Color_RedBlue
    ),
        0,
        360 * val / 255,
        30,
        (graphic_point) {
        GRAPHIC_SCREEN_WIDTH-1920+1671, 547
    },
        (graphic_point) {
        53, 53
    });
}

void graphic_draw_chassis_angle(int16_t theta) {
    static bool_t drawed = 0;
    graphic_draw_arc(graphic_data_set_inf(graphic_buffer_write(),
        GET_ID(1, 1, 0),
        drawed ? Graphic_OP_Change : (drawed = 1, Graphic_OP_Add),
        1,
        Graphic_Color_RedBlue
    ),
        theta < 0 ? (180 + theta) : 180,
        theta < 0 ? 180 : (180 + theta),
        20,
        (graphic_point) {
        GRAPHIC_SCREEN_WIDTH / 2, 180
    },
        (graphic_point) {
        100, 100
    });
}
void send_to_referee(toREF_t * data)
{
    static uint8_t usart_tx_buf[sizeof(toREF_t)];
    memcpy(usart_tx_buf, (uint8_t*)data, sizeof(toREF_t));
    usart6_tx_dma_enable(usart_tx_buf, sizeof(toREF_t));
}
/// @brief 更新graphic_now_data
void graphic_data_update()
{
    /***********绘制更新*********/
    graphic_set_super_cup(super_cup_val_tmp);
    graphic_set_chassis_angle(chassis_theta_tmp);
    /***************************/

    uint16_t i = 0;
    graphic_data_struct_t* g;
    while (i < GRAPHIC_DATA_PERTIME && (g = graphic_buffer_read())) {
        toREF_data.grapic_data_struct[i] = *g;
        ++i;
    }
    while (i < GRAPHIC_DATA_PERTIME) {
        graphic_data_set_blank(&toREF_data.grapic_data_struct[i]);
        ++i;
    }
    ui_proc_7_frame(&toREF_data, get_robot_id());
    send_to_referee(&toREF_data);
}

